from odoo import api, exceptions, fields, models, _
from odoo.exceptions import UserError, ValidationError
from odoo.osv import expression
import logging

_logger = logging.getLogger(__name__)


class MrpWorkcenter(models.Model):
    _name = 'mrp.workcenter'
    _inherit = ['mrp.workcenter', 'mail.thread', 'mail.activity.mixin']

    param_line_ids = fields.One2many('mrp.workcenter.param.line', 'workcenter_id', 'Work Center Parameters', copy=True)
    curr_user = fields.Many2one(
        string="Operator", comodel_name='res.users', default=lambda self: self.env.user, store=False)
    default_wc = fields.Boolean(
        string="Default Work Center", compute="_compute_default_wc", search="_search_default_wc")
    is_enter_bcode = fields.Boolean(string="Counting Point", default=True, tracking=True)
    is_date_code = fields.Boolean(string="DATE CODE point", default=False)
    is_sub_contract = fields.Boolean(string="Is Subcontracting", default=False)
    sub_contract_product_tmpl_id = fields.Many2one(
        'product.template', string="Subcontracting Service Product", domain="[('detailed_type', '=', 'service')]")
    move_uom_id = fields.Many2one('uom.uom', "Counting Unit", domain="[('name', 'in', ['PART','SET','PANEL'])]")
    scrapreason_ids = fields.Many2many('scrap.reason', string="Scrap Reason List")

    # department_id = fields.Many2one('hr.department', string='Department',
    #                                 help='this department must be child of Production Department')

    work_station_id = fields.Many2one('work.station', string="Work Station", tracking=True)  # jmi 工站
    s_work_station_id = fields.Many2one('work.station', string="WTT Work Station", tracking=True)  # WTT工站，用做区分，WTT有自己的绑定工站

    thai_name = fields.Char(string="Thai Name")
    eng_name = fields.Char(string="English Name")

    name = fields.Char(string="Name")
    code = fields.Char(string="Code")

    s_report_counting_point = fields.Boolean(string='report counting point', copy=False, default=False)  # 日报记算点
    s_scrap_point = fields.Boolean(string='scrap point', copy=False)  # 报废登记点
    s_scrap_available = fields.Boolean('scrap available', copy=False)  # 报废全局可用辅助字段
    # is_drill_operation = fields.Boolean(string='Drill operation?', default=False)
    # drill_image = fields.Image(string='Drill')
    s_material_category_ids = fields.Many2many(
        'product.category',
        's_mrp_workcenter_product_category',
        string='material category', copy=False
    )
    s_process_lot_name = fields.Char(string="Process Lot Name")
    s_location_id = fields.Many2one('stock.location', 'Material consumption location', copy=False)
    s_not_compute_output = fields.Boolean(string='Do not calculate production volume', copy=False, default=False)

    # @api.constrains('work_station_id', 's_report_counting_point')
    # def constrains_s_report_counting_point(self):
    #     for rec in self:
    #         if not rec.work_station_id:
    #             continue
    #         if self.search_count(
    #                 [('work_station_id', '=', rec.work_station_id.id), ('s_report_counting_point', '=', True)]) > 1:
    #             raise UserError(_('work station: %s , Counting points exceeds two', rec.work_station_id.name))

    @api.constrains('s_scrap_point')
    def constrains_scrap_point(self):
        for rec in self:
            if rec.s_scrap_point:
                rec.write({'s_report_counting_point': True, 'is_enter_bcode': True})

    @api.depends('name', 'code')
    def _compute_display_name(self):
        for rec in self:
            if rec.code and rec.name:
                rec.display_name = '[' + rec.code + ' ] ' + rec.name
            else:
                rec.display_name = rec.name

    # @api.model
    # def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
    #     domain = domain or []
    #     if name:
    #         domain = [('name', operator, name)] + domain
    #     return self._search(domain, limit=limit, order=order)

    # _sql_constraints = [
    #     ("name_uniq", "unique (name)", "That name already exists !"),
    # ]
    @api.model
    def _search_default_wc(self, operator, operand):
        return [('default_wc', operator, operand)]

    @api.model
    def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
        domain = domain or []
        if self._context.get('search_type', '') == 'scrap':
            scrap_reason_id = self._context.get('scrap_reason_id', 0)
            production_id = self._context.get('production_id', 0)
            scrap_reason_id = self.env['scrap.reason'].browse(scrap_reason_id)
            production_id = self.env['mrp.production'].browse(production_id)
            if production_id.mo_type != 'W':
                if scrap_reason_id and production_id:
                    production_ids = production_id._get_all_child()
                    production_ids |= production_id
                    workcenter_ids = production_ids.mapped('workorder_ids.workcenter_id')
                    workcenter_ids = workcenter_ids.filtered(lambda x: x in scrap_reason_id.workcenter_ids)

                    # 加上报废原因配置的全局可用工序
                    workcenter_ids |= scrap_reason_id.workcenter_ids.filtered(lambda x: x.s_scrap_available)

                    domain = expression.AND([domain, [('id', 'in', workcenter_ids.ids)]])
                else:
                    domain = [('id', '=', 0)]
                    limit = 1
            return self._search(domain, limit=limit, order=order)

        return super()._name_search(name, domain, operator, limit, order)

    @api.model
    def web_search_read(self, domain, specification, offset=0, limit=None, order=None, count_limit=None):
        if self._context.get('search_type', '') == 'scrap':
            scrap_reason_id = self._context.get('scrap_reason_id', 0)
            production_id = self._context.get('production_id', 0)
            scrap_reason_id = self.env['scrap.reason'].browse(scrap_reason_id)
            production_id = self.env['mrp.production'].browse(production_id)
            if production_id.mo_type != 'W':
                if scrap_reason_id and production_id:
                    production_ids = production_id._get_all_child()
                    production_ids |= production_id
                    workcenter_ids = production_ids.mapped('workorder_ids.workcenter_id')
                    workcenter_ids = workcenter_ids.filtered(lambda x: x in scrap_reason_id.workcenter_ids)

                    # 加上报废原因配置的全局可用工序
                    workcenter_ids |= scrap_reason_id.workcenter_ids.filtered(lambda x: x.s_scrap_available)

                    domain = expression.AND([domain, [('id', 'in', workcenter_ids.ids)]])
                else:
                    domain = [('id', '=', 0)]
                    limit = 1

        return super().web_search_read(domain, specification, offset, limit, order, count_limit)


class MrpWorkcenterParam(models.Model):
    """Attributes available on product.template with their selected values in a m2m.
    Used as a configuration model to generate the appropriate product.template.attribute.value"""
    _name = "mrp.workcenter.param.line"
    _rec_name = 'attribute_id'
    _rec_names_search = ['attribute_id']
    _description = 'Work Center Param Line'
    _order = 'sequence ASC'

    active = fields.Boolean(default=True)
    workcenter_id = fields.Many2one('mrp.workcenter', string="Work Center", ondelete='cascade',
                                    required=True, index=True)
    attribute_id = fields.Many2one('product.attribute', string="Attribute", domain="[('limit_type', '=', 'route')]",
                                   ondelete='restrict', required=True, index=True)
    thai_name = fields.Char(string="Thai Name", )
    eng_name = fields.Char(string="English Name", )

    value_id = fields.Many2one('product.attribute.value', string="Values",
                               domain="[('attribute_id', '=', attribute_id)]")

    z_thai_name = fields.Char(string="Value T Name", )
    z_eng_name = fields.Char(string="Value E Name", )
    sequence = fields.Integer(string="Sequence", default=1)

    @api.constrains('z_thai_name', 'z_eng_name', 'thai_name', 'eng_name')
    def onchange_z_name(self):
        if self.z_thai_name:
            self.value_id.thai_name = self.z_thai_name
        if self.z_eng_name:
            self.value_id.eng_name = self.z_eng_name
        if self.thai_name:
            self.attribute_id.thai_name = self.thai_name
        if self.eng_name:
            self.attribute_id.eng_name = self.eng_name

    @api.model_create_multi
    def create(self, vals_list):
        self.attribute_id = self.attribute_id.filtered(lambda pav: pav.limit_type == 'route')
        return super(MrpWorkcenterParam, self).create(vals_list)

    @api.constrains('attribute_id', 'value_id')
    @api.onchange('attribute_id', 'value_id')
    def _onchange_attribute_id(self):
        for record in self:
            if record.attribute_id:
                record.thai_name = record.attribute_id.thai_name
                record.eng_name = record.attribute_id.eng_name
            if record.value_id:
                record.z_thai_name = record.value_id.thai_name
                record.z_eng_name = record.value_id.eng_name

    # @api.onchange('attribute_id')
    # def _onchange_attribute_id(self):
    #     self.value_ids = self.value_ids.filtered(lambda pav: pav.attribute_id == self.attribute_id)

    # @api.constrains('active', 'value_ids', 'attribute_id')
    # def _check_valid_values(self):
    #     for ptal in self:
    #         if ptal.active and not ptal.value_ids:
    #             raise ValidationError(
    #                 _("The attribute %s must have at least one value for the workcenter %s.") %
    #                 (ptal.attribute_id.display_name, ptal.workcenter_id.display_name)
    #             )
    #         for pav in ptal.value_ids:
    #             if pav.attribute_id != ptal.attribute_id:
    #                 raise ValidationError(
    #                     _("On the workcenter %s you cannot associate the value %s with the attribute %s because they do not match.") %
    #                     (ptal.workcenter_id.display_name, pav.display_name, ptal.attribute_id.display_name)
    #                 )
    #     return True


class ScrapReason(models.Model):
    _name = 'scrap.reason'
    _description = 'Scrap Reason'
    _order = 'code'

    code = fields.Char('Code', required=True)
    name = fields.Char(string="Scrap Reason", required=True)
    en_name = fields.Char(string="En Name")
    work_station_ids = fields.Many2many('work.station', 's_work_station_scrap_reason_rel', string="Work Station")
    workcenter_id = fields.Many2one('mrp.workcenter', 'work center')
    workcenter_ids = fields.Many2many('mrp.workcenter')
    active = fields.Boolean('Active', default=True)

    # rej_type = fields.Selection([
    #     ('reject', 'Rejected'),
    #     ('defect', 'Defective')
    # ], string='Type', default='reject', required=True)

    @api.constrains('code')
    def constrains_code(self):
        for rec in self:
            if not rec.code:
                continue
            if self.search_count([('code', '=', rec.code)]) > 1:
                raise ValidationError('The code must be unique!')

    @api.depends('code')
    def _compute_display_name(self):
        for rec in self:
            rec.display_name = f"{rec.code or ''} - {rec.name}"
